 using UnityEngine;
using System.Collections;

public class Gemas : MonoBehaviour {
	
  //Gameobject que recolecta los cubos
	public GameObject ColeccionCubos;
	//Gameobjects para cargar los prefabs de los cubos
	public GameObject Cubo1;
	public GameObject Cubo2;
	public GameObject Cubo3;
	public GameObject Cubo4;
	public GameObject Cubo5;
	public GameObject Cubo6;
	public GameObject Cubo7;
	public GameObject Cubo8;
	
  //Numero de filas	
	static int ancho = 8;
  //Numero de columnas
	static int alto = 8;
  //Array de 2 dimensiones de numeros para guardar la posicion de las gemas
	public int[,] arrayGemas = new int[ancho,alto];
	
  //Posicion offset para centrar las gemas en pantalla
	float gemasOffsetX = -0.673f;
	float gemasOffsetY = 0.500f;
  
	int contadorGemasY = 0;
	int ultimaGemaY = -1;
	
  //Se pueden clickear las gemas ?
	public bool Clickeables = false;
  //Las gemas ya han sido creadas ?
	bool creadasGemas = false;
	
	//Lista de gemas a destruir
  ArrayList gemasDestruir = new ArrayList();
	
  //Puntuacion
	public int score = 0;
  //Numero de combinaciones seguidas, sirve de multiplicador de puntos
	public int combo = 0;
	
	//Array para controlar los sonidos aleatorios
	public AudioSource[] audioSources = new AudioSource[4];
	int contadorAS = 0;
	bool efectoInvocado = false;
	
	
	//Usar esto para inicializar
	void Start () {		

		CrearGemas();		
	}
	
	//Al despertar...
  	void Awake()
	{
				
	}
	public void CrearGemas()
	{
		if (ColeccionCubos != null)
			Destroy(ColeccionCubos);		
		
		
		Clickeables = false;
		ColeccionCubos = new GameObject("Coleccion de Gemas");
		
		//string arrayString = ""; 
		
		// Crear Gemas
		for (int i = 0; i < ancho; i++){
			//arrayGemas[i] = new int[alto];
			//arrayString += "{ ";
			for(int j = 0; j < alto; j++){
				int rnd;
				do {
					rnd = Random.Range(1, 9);
					arrayGemas[i,j] = rnd;					
				}
				while( rowLineLength(i, j) > 2 || columnLineLength(i, j) > 2);
				
				//arrayString += rnd.ToString() + ",";
					
				Vector3 pos = new Vector3( gemasOffsetX + i * 0.15f, gemasOffsetY - j * 0.15f, 0f);
				float dragRange = Random.Range(5, 7);				
				GameObject gemaInst = Instantiate( SelGema(rnd), pos, Quaternion.identity) as GameObject;
				gemaInst.transform.parent = ColeccionCubos.transform;
				gemaInst.name = i + "_" + j;
				gemaInst.transform.localScale = new Vector3(0.85f, 1.0f, 0.75f);
				Gema tempGema = gemaInst.AddComponent<Gema>();
				tempGema.IniciarGema( rnd, i, j);
				tempGema.transform.GetChild(0).rigidbody.drag = dragRange;
				//tempGema.CambiarGravedad(false);
				
			}
			//arrayString += " } \n";
			
		}		
		
		Clickeables = true;
		
		if (creadasGemas == false){
		
		StartCoroutine("Comprobar");
		//Debug.Log(arrayString);
		creadasGemas = true;
		
		}
	}	
	
  //Selector del prefab segun el numero recibido.
	GameObject SelGema ( int numero )
	{		
		if (numero > 0 && numero < 9){
			
			switch (numero)
			{
			case 1:
				return Cubo1;
			case 2:
				return Cubo2;
			case 3:
				return Cubo3;
			case 4:
				return Cubo4;
			case 5:
				return Cubo5;
			case 6:
				return Cubo6;
			case 7:
				return Cubo7;
			case 8:
				return Cubo8;
			default:
				return Cubo1;				
			}	
			
		}else{		
			return new GameObject("Fallo");			
		}		
	}
	
	//Update se llama una vez por frame (60 veces por seg. aprox.)
	void Update () {
	
		
					
	}
	
  //Comprobar combinaciones de gemas cada 0.10 segs
	IEnumerator Comprobar()
	{
		for(;;){			
			ComprobarGemas();
			yield return new WaitForSeconds(.1f);
		}
		
	}
	
	public void ComprobarGemas(){
			
		bool GemasBajando = false;
		
		for (int j = alto - 1; j >= 0; j-- ){
			for(int i = 0; i < ancho; i++){
				
				if (arrayGemas[i,j] != 0 && (j + 1) < 8 && arrayGemas[i, j + 1] == 0 ){
					
					GameObject gGem = null;
					Gema tempGem = null;
					//Debug.Log("intentando bajar gema : " + i + "_" + j);
					try{
						gGem = ColeccionCubos.transform.FindChild(i + "_" + j).gameObject;						
						tempGem = gGem.transform.GetComponent<Gema>();
						
					}catch(System.NullReferenceException ex ){
						Debug.Log(ex.Message);
						break;	
					}finally{
						if (tempGem != null){
							GemasBajando = true;	
							arrayGemas[i, j + 1] = arrayGemas[i, j];
							arrayGemas[i, j] = 0;
							tempGem.fila = j + 1;
							tempGem.columna = i;
							tempGem.gameObject.name = tempGem.columna + "_" + tempGem.fila;
							tempGem.CambiarGravedad(true);
							tempGem.Iniciada = false;
						}
					}					
					break;				
				}
			}
			if (GemasBajando)
				break;			
		}
		
		if (!GemasBajando){
			
			bool NecesitaGemas = false;
			
			for (int j = alto - 1; j >= 0; j--){
				for(int i = 0; i < ancho; i++){
					int rnd;
					if (arrayGemas[i, j]== 0){
						
						NecesitaGemas = true;
						
						if (ultimaGemaY == i)
							contadorGemasY++;
						else
							ultimaGemaY = i;
						
						rnd = Random.Range(1, 9);
						arrayGemas[i,0] = rnd;
						Vector3 pos = new Vector3( gemasOffsetX + i * 0.15f, gemasOffsetY + contadorGemasY * 0.15f, 0f);
						float dragRange = Random.Range(5, 7);				
						GameObject gemaInst = Instantiate( SelGema(rnd), pos, Quaternion.identity) as GameObject;
						gemaInst.transform.parent = ColeccionCubos.transform;
						gemaInst.name = i + "_" + 0;
						gemaInst.transform.localScale = new Vector3(0.85f, 1.0f, 0.75f);
						Gema tempGema = gemaInst.AddComponent<Gema>();
						tempGema.IniciarGema( rnd, i, 0);
						tempGema.transform.GetChild(0).rigidbody.drag = dragRange;						
						break;
						
					}									
					
				}
				if (NecesitaGemas)
					break;					
			}
			if (!NecesitaGemas){
				
				bool MasLineasDisponibles = false;
				contadorGemasY = 0;
				ultimaGemaY = -1;
				
				
				for (int j = alto - 1; j >= 0; j--){
					for(int i = 0; i < ancho; i++){
						
						if (rowLineLength(i, j) > 2 || columnLineLength(i, j) > 2){
							
							//Debug.Log("Comprobando " + i + "_" + j);
							MasLineasDisponibles = true;
							ArrayList lineaGemas = new ArrayList();
							
							GameObject tempGem = null;
							
							try{
								tempGem = ColeccionCubos.gameObject.transform.FindChild(i + "_" + j).gameObject;
							}catch(System.NullReferenceException ex){
								Debug.Log(ex.Message);
								break;	
							}							
							lineaGemas.Add(tempGem);
							int tipoGema = arrayGemas[i, j];
							int posicionLinea;
							
							if (rowLineLength(i, j) > 2){
								
								posicionLinea = j;
								while(sameGemIsHere(tipoGema, i, posicionLinea - 1)){
									posicionLinea--;
									tempGem = ColeccionCubos.gameObject.transform.FindChild(i + "_" + posicionLinea).gameObject;
									// Error NullReference
										lineaGemas.Add(tempGem);
								}
								posicionLinea = j;
								while(sameGemIsHere(tipoGema, i, posicionLinea + 1)){
								
									posicionLinea++;
									tempGem = ColeccionCubos.gameObject.transform.FindChild(i + "_" + posicionLinea).gameObject;
									// Error NullReference
										lineaGemas.Add(tempGem);
									
								}
								
							}
							if (columnLineLength(i, j) > 2){
							
								posicionLinea=i;
								while( sameGemIsHere(tipoGema, posicionLinea - 1, j)){
									
									posicionLinea--;
									tempGem = ColeccionCubos.gameObject.transform.FindChild( posicionLinea + "_" + j ).gameObject;
									// Error NullReference
										lineaGemas.Add(tempGem);
									
								}
								while( sameGemIsHere(tipoGema, posicionLinea + 1, j)){
									
									posicionLinea++;
									try{
										//Debug.Log("Same Gem is Here : " + posicionLinea + "_" + j);
									tempGem = ColeccionCubos.gameObject.transform.FindChild(posicionLinea + "_" + j ).gameObject;
									}catch(System.NullReferenceException ex){
										Debug.Log(ex.Message);
										break;
									}finally{
										lineaGemas.Add(tempGem);
									}
									
								}
							}
							
							if (lineaGemas.Count > 0 ){
								
								foreach ( GameObject go in lineaGemas){			
									
									if (!gemasDestruir.Contains(go)){
										go.GetComponent<Gema>().Seleccionada = true;
										gemasDestruir.Add(go);
									}
								}
								
								lineaGemas.Clear();
								
								Invoke("DestruirGemas", 0.5f);
								if (!efectoInvocado){
									Invoke("ReproducirSonido", 0.5f);
									efectoInvocado = true;
								}
								
							}
							
							lineaGemas.Clear();
							break;
						}
					}
					if (MasLineasDisponibles)
						break;
				}
				if (!MasLineasDisponibles){
					
					Clickeables = true;
					
					
					
				}
			}
		}	
	}
	
	void DestruirGemas(){
		
		combo = 0;
		
		foreach ( GameObject go in gemasDestruir){
			
			//Debug.Log("Eliminando gema : " + tempGema.columna + "_" + tempGema.fila);
			Gema tempGema = go.gameObject.transform.GetComponent<Gema>();								
			arrayGemas[tempGema.columna, tempGema.fila] = 0;
			Destroy(go);					
			score += combo;								
			combo++;			
		}
		gemasDestruir.Clear();
	}
	
	void ReproducirSonido(){
		int rnd = Random.Range(0, 3);		
		audioSources[rnd].Play();
		efectoInvocado = false;
	}
	void ReproducirSonido(int i){
		audioSources[i].Play();
		efectoInvocado = false;
	}
  //Mover las gemas de una posicion a otra
	public void swapGems(int fromRow, int fromColumn, int toRow, int toColumn) {
			
			
			int originalPosition = arrayGemas[fromColumn, fromRow];
			
			arrayGemas[fromColumn, fromRow] = arrayGemas[toColumn, toRow];
			
			arrayGemas[toColumn, toRow] = originalPosition;
		
			//Debug.Log("Movido " + fromColumn  + "_" + fromRow + " a " + toColumn  + "_" + toRow);
	}
	
	//Buscar lineas horizontales
	public int rowLineLength(int row, int column) {			
			
		int t_gema = arrayGemas[row,column];
		int lineLength = 1;
		int checkColumn = column;
		//comprobar hasta donde se extiende hacia la izquierda
		while (sameGemIsHere(t_gema,row,checkColumn-1)) {
			checkColumn--;
			lineLength++;
		}
		checkColumn=column;
		//comprobar hasta donde se extiende hacia la derecha
		while (sameGemIsHere(t_gema,row,checkColumn+1)) {
			checkColumn++;
			lineLength++;
		}
		// devuelve la cantidad de gemas seguidas
		return lineLength;
	}
	//Buscar lineas verticales
	public int columnLineLength( int row, int column){
		
		int gemType = arrayGemas[row,column];
		int lineLength = 1;
		int checkRow = row;
		//comprobar hasta donde se extiende hacia abajo
		while (sameGemIsHere(gemType,checkRow-1,column)) {
			checkRow--;
			lineLength++;
		}
		//comprobar hasta donde se extiende hacia arriba
		checkRow=row;
		while (sameGemIsHere(gemType,checkRow+1,column)) {
			checkRow++;
			lineLength++;
		}
		// devuelve la cantidad de gemas seguidas
		return lineLength;
	}
	
	public bool sameGemIsHere(int gemType,int row, int column) {
		//Comprueba si hay gemas en la posicion indicada
		//Debug.Log("Comprobando Row : " + row  + " Col : " + column + " Tipo : " + gemType);
		if ( arrayGemas[row, column] == null ) {
			//Debug.Log("Se devolvio false por null, en el metodo sameGemIsHere");
			return false;			
		}		
		//Comprueba si posicion de la gema es correcta
		if ( row < 0 || row > alto - 1|| column > ancho - 1 || column < 0 || arrayGemas[row, column]==0) {
			//Debug.Log("Se devolvio false, en el metodo sameGemIsHere");
			return false;
		}
		
		//Debug.Log("Comparando gemas tipo: " + gemType);
		//Si es correcta, comprueba que sea del mismo tipo, y devuelve un true o false
		return arrayGemas[row, column] == gemType;
	}
}
